package com.tcm.prescribe.service;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.base.core.dozer.DozerConvert;
import com.base.core.exception.ServiceException;
import com.base.core.lang.StringUtils;
import com.base.core.pager.PageBean;
import com.base.core.pager.PageContext;
import com.base.core.utils.ListUtils;
import com.base.core.utils.R;
import com.base.genid.generator.UidGenerator;
import com.tcm.prescribe.api.domain.dto.PrescribeDetailDTO;
import com.tcm.prescribe.api.domain.dto.PrescribeDrugsDTO;
import com.tcm.prescribe.api.domain.dto.PrescribeDTO;
import com.tcm.prescribe.api.domain.dto.PrescribeRecordDTO;
import com.tcm.prescribe.api.domain.entity.Prescribe;
import com.tcm.prescribe.api.domain.entity.PrescribeDrugs;
import com.tcm.prescribe.api.domain.enums.BusinessCodeEnum;
import com.tcm.prescribe.api.service.PrescribeService;
import com.tcm.prescribe.api.service.WebService;
import com.tcm.prescribe.mapper.PrescribeDrugsMapper;
import com.tcm.prescribe.mapper.PrescribeMapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@DubboService(version = "0.0.1-alpha", retries = 3, timeout = 6000)
public class PrescribeServiceImpl implements PrescribeService {

    @Autowired
    private PrescribeMapper prescribeMapper;

    @Autowired
    private PrescribeDrugsMapper prescribeDrugsMapper;


    @DubboReference(version = "0.0.1-beta", group = "cached-uid", timeout = 6000, check = false, retries = 3)
    private UidGenerator uidGenerator;

    @Autowired
    private WebService webService;

    @Transactional
    @Override
    public Long save(PrescribeDTO prescribeDto) throws ServiceException{
        if (ObjectUtil.isEmpty(prescribeDto.getDoctorId())) {
            R.throwFail(BusinessCodeEnum.DOCTOR_ID_NOT_EXISTS);
        }
        if (ObjectUtil.isEmpty(prescribeDto.getStoreId())) {
            R.throwFail(BusinessCodeEnum.STORE_ID_NOT_EXISTS);
        }
        if (ListUtils.isEmpty(prescribeDto.getPrescribeDrugs())) {
            R.throwFail(BusinessCodeEnum.DRUGS_NOT_EXISTS);
        }
        if (StringUtils.isEmpty(prescribeDto.getSource())) {
            R.throwFail(BusinessCodeEnum.SOURCE_ID_NOT_EXISTS);
        }
        try {
            Prescribe prescribe = DozerConvert.copyProperties(prescribeDto, Prescribe.class);

            prescribe.setId(uidGenerator.getUID());
            prescribe.setCreateTime(LocalDateTime.now());
            prescribe.setUpdateTime(LocalDateTime.now());
            prescribe.setStatus(new Byte("1"));//默认已审核
            prescribe.setIsUse(new Byte("0"));
            prescribe.setDeleted(new Byte("0"));
            prescribe.setTotalServiceMoney(
                    NumberUtil.mul(
                            prescribe.getQuantity(),
                            prescribe.getServiceMoney()
                    )
            );
            prescribe.setTotalDrugMoney(
                    NumberUtil.mul(
                            prescribe.getQuantity(),
                            prescribe.getDrugMoney()
                    )
            );
            prescribe.setTotalMoney(
                    NumberUtil.add(
                            prescribe.getBillingMoney(),
                            NumberUtil.mul(prescribe.getDrugMoney(), prescribe.getQuantity()),
                            NumberUtil.mul(prescribe.getServiceMoney(), prescribe.getQuantity())
                    )
            );
            List<PrescribeDrugsDTO> treatmentDrugsList = prescribeDto.getPrescribeDrugs();
            List<PrescribeDrugs> prescribeDrugs = DozerConvert.copyList(treatmentDrugsList, PrescribeDrugs.class);
            for (PrescribeDrugs prescribeDrug : prescribeDrugs) {
                prescribeDrug.setId(uidGenerator.getUID());
                prescribeDrug.setCreateTime(LocalDateTime.now());
                prescribeDrug.setUpdateTime(LocalDateTime.now());
                prescribeDrug.setDeleted(new Byte("0"));
                prescribeDrug.setPrescribeId(prescribe.getId());
                if (ObjectUtil.isEmpty(prescribeDrug.getRemark())) {
                    prescribeDrug.setRemark("");
                }
            }
            prescribe.setExpire(48);//默认48小时
            prescribeMapper.insert(prescribe);
            prescribeDrugsMapper.insertBatch(prescribeDrugs);
            return prescribe.getId();
        }catch (Exception e){
            R.throwFail(e.getMessage());
        }
        return 0L;
    }

    @Transactional
    @Override
    public void update(PrescribeDTO prescribeDto) throws ServiceException {
        if (ObjectUtil.isEmpty(prescribeDto.getDoctorId())) {
            R.throwFail(BusinessCodeEnum.DOCTOR_ID_NOT_EXISTS);
        }
        if (ListUtils.isEmpty(prescribeDto.getPrescribeDrugs())) {
            R.throwFail(BusinessCodeEnum.DRUGS_NOT_EXISTS);
        }
        if (ObjectUtil.isEmpty(prescribeDto.getId())) {
            R.throwFail(BusinessCodeEnum.PLAN_ID_NOT_EXISTS);
        }
        try {
            Prescribe prescribe = DozerConvert.copyProperties(prescribeDto, Prescribe.class);
            prescribe.setUpdateTime(LocalDateTime.now());
            prescribe.setStatus(new Byte("0"));
            prescribe.setRemark("");
            prescribe.setTotalServiceMoney(
                    NumberUtil.mul(
                            prescribe.getQuantity(),
                            prescribe.getServiceMoney()
                    )
            );
            prescribe.setTotalDrugMoney(
                    NumberUtil.mul(
                            prescribe.getQuantity(),
                            prescribe.getDrugMoney()
                    )
            );
            prescribe.setTotalMoney(
                    NumberUtil.add(
                            prescribe.getBillingMoney(),
                            NumberUtil.mul(prescribe.getDrugMoney(), prescribe.getQuantity()),
                            NumberUtil.mul(prescribe.getServiceMoney(), prescribe.getQuantity())
                    )
            );
            List<PrescribeDrugsDTO> treatmentDrugsList = prescribeDto.getPrescribeDrugs();
            List<PrescribeDrugs> prescribeDrugs = DozerConvert.copyList(treatmentDrugsList, PrescribeDrugs.class);
            for (PrescribeDrugs prescribeDrug : prescribeDrugs) {
                prescribeDrug.setId(uidGenerator.getUID());
                prescribeDrug.setCreateTime(LocalDateTime.now());
                prescribeDrug.setUpdateTime(LocalDateTime.now());
                prescribeDrug.setDeleted(new Byte("0"));
                prescribeDrug.setPrescribeId(prescribeDto.getId());
            }
            //优先删除处方药品
            prescribeDrugsMapper.deleteByPrescribeId(prescribe.getId());
            prescribeMapper.update(prescribe);
            prescribeDrugsMapper.insertBatch(prescribeDrugs);
        }catch (Exception e){
            R.throwFail(e.getMessage());
        }

    }

    /**
     * 患者端处方列表
     * @param userId 用户uid
     * @param start 当前页码
     * @param pagesize 每页记录
     * @return
     */
    @Override
    public PageBean<PrescribeDTO> listUserPrescribePage(Long userId, Long start, Long pagesize) throws ServiceException {
        Long dataCount = prescribeMapper.countUserPrescribe(userId);
        if(dataCount.intValue() == 0){
            return new PageBean<>(null);
        }
        PageContext.setCurrentPage(Long.valueOf(start));
        PageContext.setPageSize(Long.valueOf(pagesize));
        PageContext.setDataCount(dataCount);
        List<Prescribe> prescribeList = prescribeMapper.listUserPrescribePage(userId, PageContext.getStart(), PageContext.getPageSize());
        List<PrescribeDTO> prescribeDTOS = DozerConvert.copyList(prescribeList, PrescribeDTO.class);
        PageBean<PrescribeDTO> prescribeDTOPageBean = new PageBean<>(prescribeDTOS);
        return prescribeDTOPageBean;
    }

    /**
     * 医生端用药管理列表
     * @param userId 医生用户id
     * @param start 当前页
     * @param pagesize 每页记录数
     * @return
     */
    @Override
    public PageBean<PrescribeDTO> listDoctorPrescribePage(Long userId, Long start, Long pagesize) {
        Long dataCount = prescribeMapper.countDoctorPrescribe(userId);
        PageContext.setCurrentPage(Long.valueOf(start));
        PageContext.setPageSize(Long.valueOf(pagesize));
        PageContext.setDataCount(dataCount);
        if(dataCount.intValue() == 0){
            return new PageBean<>(null);
        }

        List<Prescribe> prescribeList = prescribeMapper.listDoctorPrescribePage(userId, PageContext.getStart(), PageContext.getPageSize());
        List<PrescribeDTO> prescribeDTOS = DozerConvert.copyList(prescribeList, PrescribeDTO.class);
        PageBean<PrescribeDTO> prescribeDTOPageBean = new PageBean<>(prescribeDTOS);
        return prescribeDTOPageBean;
    }

    @Transactional
    @Override
    public void deleteLogicById(Long id) {
        prescribeMapper.deleteLogicById(id);
        prescribeDrugsMapper.deleteLogicByPrescribeId(id);
    }

    @Transactional
    @Override
    public void deleteById(Long id) {
        prescribeMapper.deleteById(id);
        prescribeDrugsMapper.deleteByPrescribeId(id);
    }

    /**
     * 更新购药状态
     *
     * @param id
     */
    @Override
    public void updateIsUse(Long id) throws ServiceException{
        Prescribe prescribe = prescribeMapper.findById(id);
        if(ObjectUtil.isEmpty(prescribe)){
            R.throwFail(BusinessCodeEnum.PLAN_NOT_EXISTS);
        }
        try {
            prescribeMapper.changeUsed(id);
        }catch (Exception e){
            R.throwFail(e.getMessage());
        }
    }

    @Override
    public PrescribeDTO findById(Long planId) {
        Prescribe prescribe = prescribeMapper.findById(planId);
        if(ObjectUtil.isEmpty(prescribe)){
            return null;
        }
        List<PrescribeDrugs> prescribeDrugsList = prescribeDrugsMapper.listByPrescribeId(planId);
        PrescribeDTO prescribeDTO = DozerConvert.copyProperties(prescribe, PrescribeDTO.class);
        List<PrescribeDrugsDTO> prescribeDrugsDTOS = DozerConvert.copyList(prescribeDrugsList, PrescribeDrugsDTO.class);
        prescribeDTO.setPrescribeDrugs(prescribeDrugsDTOS);
        return prescribeDTO;
    }

    /**
     * 更新购药状态
     *
     * @param id
     */
    @Override
    public void verifyPassed(Long id) throws ServiceException {
        Prescribe prescribe = prescribeMapper.findById(id);
        if(ObjectUtil.isEmpty(prescribe)){
            R.throwFail(BusinessCodeEnum.PLAN_NOT_EXISTS);
        }
        try {
            prescribeMapper.verifyPass(id);
        }catch (Exception e){
            R.throwFail(e.getMessage());
        }

    }

    /**
     * 审核驳回
     *
     * @param id
     * @param remark
     */
    @Override
    public void verifyRefused(Long id, String remark) {
        Prescribe prescribe = prescribeMapper.findById(id);
        if(ObjectUtil.isEmpty(prescribe)){
            R.throwFail(BusinessCodeEnum.PLAN_NOT_EXISTS);
        }
        try {
            prescribeMapper.verifyRefused(id, remark);
        }catch (Exception e){
            R.throwFail(e.getMessage());
        }
    }

    /**
     * 发送方案
     *
     * @param id
     */
    @Override
    public String sendWebService(Long id) {
        //发送方案
        PrescribeDTO prescribe = findById(id);

        if (ObjectUtil.isNull(prescribe)) {
            R.throwFail(BusinessCodeEnum.PLAN_ID_NOT_EXISTS);
        }

        PrescribeRecordDTO prescriberecord = new PrescribeRecordDTO();
        prescriberecord.setId(id.toString());
        prescriberecord.setName(prescribe.getUserName());
        prescriberecord.setSex(prescribe.getSex().toString());
        prescriberecord.setAge(prescribe.getAge().toString());
        prescriberecord.setTele(prescribe.getUserPhone());
        prescriberecord.setDepartmentName(prescribe.getDepartment());
        prescriberecord.setDoctorName(prescribe.getDoctorName());
        prescriberecord.setCreatorName(null);
        prescriberecord.setCreationTime(null);
        prescriberecord.setQuantity(NumberUtil.mul(prescribe.getQuantity(), new BigDecimal("2")).toString());
        prescriberecord.setQuantityDay(prescribe.getQuantity().toString());
        prescriberecord.setPrice(NumberUtil.round(prescribe.getDrugMoney(), 3).toString());
        prescriberecord.setPriceTotal(NumberUtil.round(NumberUtil.mul(prescribe.getDrugMoney(),prescribe.getQuantity()),3).toString());
        prescriberecord.setPaymentType("自费");
        prescriberecord.setPaymentStatus("PAYED");
        prescriberecord.setDataSource("HIS");
        prescriberecord.setDeviceId(null);
        prescriberecord.setProcessStatus("NEW");
        int no = 1;
        List<PrescribeDetailDTO> prescribedetails = new ArrayList<PrescribeDetailDTO>();
        for (PrescribeDrugsDTO prescribeDrug : prescribe.getPrescribeDrugs()) {
            PrescribeDetailDTO prescribedetail = new PrescribeDetailDTO();
            prescribedetail.setId(prescribe.getId().toString());
            prescribedetail.setNo(String.valueOf(no));
            no++;
            prescribedetail.setGranuleId(prescribeDrug.getDrugsNo());
            prescribedetail.setGranuleName(prescribeDrug.getName());
            prescribedetail.setDoseHerb(prescribeDrug.getQuantity().toString());
            prescribedetail.setEquivalent("0");
            prescribedetail.setDose("0");
            prescribedetail.setPrice(NumberUtil.round(NumberUtil.mul(NumberUtil.round(prescribeDrug.getSalePrice(), 3),
                    prescribeDrug.getQuantity()), 3).toString());
            prescribedetails.add(prescribedetail);
        }

        prescriberecord.setPrescribeDetails(prescribedetails);
        return webService.createParams(prescriberecord);


    }

}
